package com.dangs.downloader;

import android.Manifest;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;


import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MainActivity extends AppCompatActivity implements HttpHelper.DownloadInterface {

    final String TAG = "NetTool";
    private FrameLayout bg;
    private Button startButton, searchButton;
    private EditText ipEdit, threadEdit;
    private TextView infoText;
    private ProgressBar progressBar;
    private ListView fileList;
    private long totalTime, fileSize;

    int[] colors = {Color.WHITE, Color.BLACK, Color.RED, Color.GREEN, Color.YELLOW, Color.GRAY};
    private boolean isDownloading = false;
    private HttpHelper httpHelper;
    private String serverIP = "";
    private String serverPort = "";
    private String file = "";
    private List<String> files = new ArrayList<>();
    private ArrayAdapter<String> adapter;
    private final int DEFAULT_THREAD_COUNT = 4;
    private int threadCount = DEFAULT_THREAD_COUNT;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        httpHelper = HttpHelper.getInstance(this);
        requestPermission();
        bg = findViewById(R.id.bg);
        ipEdit = findViewById(R.id.et_ip);
        threadEdit = findViewById(R.id.et_thread);
        threadEdit.setText(String.valueOf(DEFAULT_THREAD_COUNT));
        progressBar = findViewById(R.id.progress);
        findViewById(R.id.bt_search).setOnClickListener(v -> searchValidFile());
        findViewById(R.id.bt_start).setOnClickListener(v -> download(ipEdit.getText().toString()));
        infoText = findViewById(R.id.tx_info);
        infoText.setText(getString(R.string.host_ip) + HttpHelper.getHostIP());
        fileList = findViewById(R.id.list);
        fileList.setOnItemClickListener((parent, view, position, id) -> download(files.get(position)));
        adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, files);
        fileList.setAdapter(adapter);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return super.onKeyDown(keyCode, event);
    }

    public static String getIP(String text) {
        Pattern p = Pattern.compile("([0-9]{1,3}\\.)([0-9]{1,3}\\.)([0-9]{1,3}\\.)([0-9]{1,3})", Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(text);
        if (matcher.find()) {
            return matcher.group();
        }
        return "";
    }

    public static String getPort(String text) {
        Pattern p = Pattern.compile(":[0-9]{1,6}", Pattern.CASE_INSENSITIVE);
        Matcher matcher = p.matcher(text);
        if (matcher.find()) {
            return matcher.group().substring(1);
        }
        return "";
    }

    private void searchValidFile() {
        String info = ipEdit.getText().toString();
        if (TextUtils.isEmpty(info)) {
            Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_SHORT).show();
            return;
        }
        //get IP
        String ip = getIP(info);
        if (TextUtils.isEmpty(ip)) {
            Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_SHORT).show();
            return;
        }
        serverIP = ip;
        String port = getPort(info);
        if (TextUtils.isEmpty(port)) {
            Toast.makeText(this, R.string.use_default_port, Toast.LENGTH_SHORT).show();
            port = "2222";
        }
        serverPort = port;
        new Thread(new GetFileListRunnable()).start();
    }

    private void download(String path) {
        if (isDownloading) {
            Toast.makeText(this, R.string.downloading, Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(path)) {
            Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            threadCount = Integer.parseInt(threadEdit.getText().toString());
        } catch (NumberFormatException e) {
            L.w(TAG, "can't parse from text, err:" + e.toString());
            threadCount = DEFAULT_THREAD_COUNT;
        }
        if (path.contains("http")) {
            httpHelper.download(path, threadCount);
        } else {
            file = path;
            String url = "http://" + serverIP + ":" + serverPort + "/" + file;
            httpHelper.download(url, threadCount);
        }
    }


    private void requestPermission() {
        String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
        ActivityCompat.requestPermissions(this, permissions, 101);
    }


    @Override
    public void onStartDownload(long startTime) {
        L.d(TAG, "onStartDownload:" + startTime);
        isDownloading = true;
        runOnUiThread(() -> {
            progressBar.setVisibility(View.VISIBLE);
        });
    }

    @Override
    public void onGetFileSize(long fileSize) {
        L.d(TAG, "onGetFileSize:" + fileSize);
        this.fileSize = fileSize;
    }

    @Override
    public void onDownloading(long progress, float speed) {
//        L.d(TAG, "onDownloading:" + progress);
        runOnUiThread(() -> {
            StringBuilder builder = new StringBuilder();
            builder.append(getString(R.string.downloading)).append(":").append(file).append("    ")
                    .append(getString(R.string.download_progress)).append(":").append(progress).append("%    ")
                    .append(getString(R.string.net_speed)).append(":").append(speed).append("Mb/s");
            infoText.setText(builder.toString());
            if (progress <= 100 && progress >= 0) {
                progressBar.setProgress((int) progress);
            }
        });
    }

    @Override
    public void onDownloadErr(Exception e) {
        String errInfo = getString(R.string.download_err) + ":" + e.toString();
        runOnUiThread(() -> {
            Toast.makeText(this, errInfo, Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    public void onDownloadComplete(long totalTime) {
        L.d(TAG, "onDownloadComplete, total time:" + totalTime);
        isDownloading = false;
        this.totalTime = totalTime;
        runOnUiThread(() -> {
            progressBar.setVisibility(View.INVISIBLE);
            if (totalTime > 0) {
                float speed = fileSize * 1000 * 8.0f / (totalTime * 1024 * 1024);
                infoText.setText(R.string.average_speed);
                infoText.append(speed + "Mb/s");
            } else {
                infoText.setText(getString(R.string.host_ip) + HttpHelper.getHostIP());
            }
        });
    }

    class GetFileListRunnable implements Runnable {
        @Override
        public void run() {
            String url = "http://" + serverIP + ":" + serverPort;
            List<String> list = HttpHelper.getHttpText(url, "checkbox");
            L.d(TAG, "get file list:" + list);
            if (list.size() > 0) {
                files.clear();
                files.addAll(list);
                runOnUiThread(() -> adapter.notifyDataSetChanged());
            } else {
                runOnUiThread(() -> {
                    Toast.makeText(MainActivity.this, R.string.no_find_file, Toast.LENGTH_SHORT).show();
                });
            }
        }
    }
}